<html>
<head>
<title>CpcPaChi - Version 0.11</title>
<style type="text/css">
span {
	font-family: 'Courier New';
	font-size: 10pt;
	color: #000000;
}
.sc0 {
	color: #808080;
}
.sc3 {
	color: #008080;
}
.sc4 {
	color: #FF8000;
}
.sc5 {
	font-weight: bold;
	color: #0000FF;
}
.sc7 {
	color: #808080;
}
.sc9 {
	color: #804000;
}
.sc10 {
	font-weight: bold;
	color: #000080;
}
.sc11 {
}
</style>
</head>
<body>
<h2>Un compilador sencillo paso a paso (11 - Saltos incondicionales)</h2>

<p align="right">(Volver al <a href="doc.html">&iacute;ndice</a>) </p>

<p>Las estructuras condicionales, como &quot;if&quot;, y las repetitivas como
&quot;while&quot; y &quot;for&quot;, cuando se conviertan a c&oacute;digo m&aacute;quina,
necesitar&aacute;n realizar saltos a partes anteriores o posteriores
del programa. Por eso, como forma de acercarnos a esa problem&aacute;tica, vamos
a crear saltos incondicionales: la peligrosa orden &quot;goto&quot;.</p>

<p>Eso supone que tambi&eacute;n podamos definir etiquetas, para indicar a
qu&eacute; lugar queremos saltar. En Pascal, quedar&iacute;a algo como:</p>

<pre><code>label destino;
begin
  ...
  destino:
  ...
  goto destino;
  ...
end.</code></pre>

<p>La forma m&aacute;s sencilla (aunque poco eficiente) de convertirlo a
c&oacute;digo m&aacute;quina es usar saltos a direcciones absolutas de memoria.
Por ejemplo, un salto atr&aacute;s en ensamblador quedar&iacute;a as&iacute;:</p>

<pre><code>
  ...
  .destino
  ...
  jp destino
  ...
</code></pre>

<p>La traducci&oacute;n a ensamblador es pr&aacute;cticamente inmediata.
Pero nosotros no queremos compilar a ensamblador, sino directamente a
c&oacute;digo m&aacute;quina, de modo que no podemos emplear etiquetas, sino que
debemos indicar a qu&eacute; posicion de memoria queremos saltar. Si se trata
de una posici&oacute;n de memoria anterior, no es d&iacute;ficil: como ya la
conocemos, podr&iacute;amos construir sin problemas la orden de salto:
</p>

<pre><code>
  30000: ...
  ...
  C3 30 75; jp 30000
  ...
</code></pre>

<p>Pero si se trata de un salto hacia un punto posterior, estamos atados
de manos: todav&iacute;a no sabemos de qu&eacute; direcci&oacute;n de memoria se trata, lo que
nos obliga a &quot;retroceder&quot; cuando ya la conozcamos: en ensamblador ser&iacute;a
</p>

<pre><code>
  ...
  jp destino
  ...
  .destino
  ...  
</code></pre>

<p>Que en c&oacute;digo m&aacute;quina se convertir&iacute;a en:
</p>

<pre><code>
  ...
  C3 ?? ?? ; jp ????
  ...
</code></pre>

<p>Esas &quot;interrogaciones&quot; representan lo que todav&iacute;
a no sabemos, huecos que tendremos que rellenar m&aacute;s 
adelante, y que nos obligar&aacute;n a dar una segunda pasada 
(aunque sencilla). Como estamos volcando a fichero a medida que 
compilamos, tenemos dos opciones</p> 

<ul>
  <li>Conservar todo el programa en memoria, para poder dar la segunda
    pasada antes de volcar a disco.</li>
  <li>Tras terminar la primera pasada, volver a abrir el fichero generado
    para dar la segunda pasada, volcando el resultado a un nuevo fichero.</li>
</ul>

<p>La primera opci&oacute;n ser&iacute;a la m&aacute;s eficiente en 
cuanto a velocidad, pero necesita m&aacute;s espacio en memoria, y 
partimos de la idea de que quiz&aacute; alg&uacute;n d&iacute;a el 
compilador llegue a poder compilarse a s&iacute; mismo y funcionar 
desde la m&aacute;quina de destino, un equipo con unos 64 Kb de 
memoria. Por eso, consideraremos la memoria como un bien muy valioso, 
y seguiremos volcando a disco, para dar una segunda pasada sobre ese 
fichero resultante en disco.
</p> 

<p>As&iacute;, el resultado de la primera salida para esa instrucci&oacute;n de
salto podr&iacute;a ser algo como:
</p>

<pre><code>
  ...
  DATA,C3,destinoLOW,destinoHIGH ; jp destino
  ...
</code></pre>

<p>(Lo de descomponer &quot;destino&quot; en &quot;destinoLOW&quot; y &quot;destinoHIGH&quot; es
porque en la m&aacute;quina que estamos tomando como destino se sigue
el criterio habitual de codificar los datos de m&aacute;s de un byte
como el byte menos significativo seguido por el m&aacute;s significativo
-&quot;little endian&quot;).
</p>

<p>La segunda pasada podr&iacute;a buscar cada uno de los identificadores
de la tabla de s&iacute;mbolos (como &quot;destino&quot;) para ver si aparecen
descompuestos en &quot;destinoLOW&quot; y &quot;destinoHIGH&quot; 
y reemplazarlos por sus valores.
</p>

<p>Ya que vamos a dar dos pasadas, podemos optimizar algo que antes
hab&iacute;amos hecho de una forma sencilla pero no demasiado correcta:
podemos dejar las variables a continuaci&oacute;n del c&oacute;digo, en vez
de colocarlas al principio y separadas del c&oacute;digo por un espacio
arbitrario. Ahora otros fragmentos de nuestro c&oacute;digo ser&aacute;n cosas como:
</p>

<pre><code>
  ...
  DATA,3E,[xBYTE] ; LD A, variableX
  ...
</code></pre>

<p>Y el espacio para esa &quot;variableX&quot; se reservar&iacute;a al final, de la
primera pasada, tras el c&oacute;digo del programa, y el valor exacto
de la direcci&oacute;n se sustituir&iacute;a en la segunda pasada.</p>

<p>Aun as&iacute;, esa mejora de momento la aplazamos para algo m&aacute;s adelante...</p>

<p><br>
  Como siempre, para m&aacute;s detalles, todo el c&oacute;digo est&aacute; en la p&aacute;gina del proyecto en Google Code:<br />
  <br />
  <a href="http://code.google.com/p/cpcpachi/">http://code.google.com/p/cpcpachi/</a></p>
<p align="right">(Volver al <a href="doc.html">&iacute;ndice</a>) </p>
</body>
</html>
